// 
// SoapTrace.Net - A soap message monitoring utility. 
// 
// Copyright (C) 2004-2009 Matthew Ward
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// 
// Matthew Ward (mrward@users.sourceforge.net)
// 

using SoapTrace.Core.Diagnostics;
using SoapTrace.Core.Formatters;
using System;
using System.Configuration;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;

namespace SoapTrace.Core
{
	/// <summary>
	/// The Soap Trace application's configuration.
	/// </summary>
	[ XmlType( "soaptrace.config" ) ]
	public class SoapTraceConfiguration
	{
		/// <summary>
		/// The name of the config file that will hold user specific
		/// settings.
		/// </summary>
		public const string UserConfigurationFilename 
			= "SoapTrace.exe.user.config";
		
		/// <summary>
		/// The name of the config section that this class maps to.  This needs to
		/// be the same as the XmlType attribute name on the 
		/// class.
		/// </summary>
		public const string ConfigSectionName =
			"soaptrace.config";
				
		/// <summary>
		/// Flag that specifies whether the debug message menu option is enabled.
		/// </summary>
		private bool m_DebugMessages;
		
		/// <summary>
		/// The number of debug messages to save.
		/// </summary>
		private int m_DebugMessagesCount;
		
		/// <summary>
		/// The debug log level to use whilst running.
		/// </summary>
		private LogLevel m_DebugLogLevel = LogLevel.Info;
		
		/// <summary>
		/// Whether to log bytes as a string or as a set of bytes. When 
		/// the SoapTrace app is working with plain HTTP logging the bytes
		/// as a string is easier to read.
		/// </summary>
		private bool m_DebugLogBytesAsString = true;
		
		/// <summary>
		/// Message formatters that are available.
		/// </summary>
		private MessageFormatterEntryCollection m_FormatterEntries = 
			new MessageFormatterEntryCollection( );
		
		/// <summary>
		/// The main form's configuration.
		/// </summary>
		private MainFormConfiguration m_MainFormConfig = 
			new MainFormConfiguration( );
		
		/// <summary>
		/// The soap message logger's configuration.
		/// </summary>
		private SoapMessageLoggerConfiguration m_SoapMessageLoggerConfig = 
			new SoapMessageLoggerConfiguration( );
		
		/// <summary>
		/// A collection of monitor manager's config objects.
		/// </summary>
		private MonitorManagerConfigurationCollection m_MonitorManagers =
			new MonitorManagerConfigurationCollection( );
		
		/// <summary>
		/// A collection of closed monitor manager's config objects.
		/// </summary>
		private MonitorManagerConfigurationCollection m_ClosedMonitorManagers =
			new MonitorManagerConfigurationCollection( );
		
		/// <summary>
		/// The maximum number of closed monitor manager's to keep.
		/// </summary>
		private int m_MaxCloseHistoryItems = 5;
 
		/// <summary>
		/// Creates a new instance of the <see cref="SoapTraceConfiguration"/>
		/// class.
		/// </summary>
		public SoapTraceConfiguration( )
		{
		}

		/// <summary>
		/// Gets the folder that will be used to store the 
		/// user's configuration.
		/// </summary>
		public static string UserConfigurationFolder 
		{
			get
			{
				return Path.Combine( Environment.GetFolderPath( Environment.SpecialFolder.LocalApplicationData ), 
					"SoapTrace.Net" );
			}
		}
		
		/// <summary>
		/// Loads the soap trace application's configuration.
		/// </summary>
		public static SoapTraceConfiguration Load( )
		{
			SoapTraceConfiguration Config = null;
			
			if( UserSettingsExist )
			{
				// Read user settings.
				
				Logger.Log( String.Concat( "Reading user's local config settings. '", UserConfigurationFullFilename, "'." ) );
				Config = Load( UserConfigurationFullFilename );
			}
			else
			{
				// User the application's settings.
				
				Logger.Log( String.Concat( "No user settings. Reading app.config. User settings filename '", UserConfigurationFullFilename, "'." ) );
				Config = ( SoapTraceConfiguration )ConfigurationManager.GetSection( ConfigSectionName );
			}
			
			return Config;
		}
		
		/// <summary>
		/// Loads the soap trace application's configuration.
		/// </summary>
		/// <param name="reader">A <see cref="TextReader"/>.</param>
		/// <returns>A <see cref="SoapTraceConfiguration"/> object.</returns>
		public static SoapTraceConfiguration Load( TextReader reader )
		{
			// Read the configuration.
			
       		XmlSerializer Serializer = 
				new XmlSerializer( typeof( SoapTraceConfiguration ) );
			
       		SoapTraceConfiguration Config =
               ( SoapTraceConfiguration )Serializer.Deserialize( reader );
       		
       		reader.Close( );
			
			return Config;				
		}
		
		/// <summary>
		/// Loads the soap trace application's configuration.
		/// </summary>
		/// <param name="filename">The full filename of the config file.</param>
		/// <returns>A <see cref="SoapTraceConfiguration"/> object.</returns>
		public static SoapTraceConfiguration Load( string filename )
		{
			// Read the configuration.
			
			StreamReader Reader = new StreamReader( filename, Encoding.UTF8, true );

			return Load( Reader );
		}

		/// <summary>
		/// Saves the current user's configuration settings.
		/// </summary>
		public void Save( )
		{
			string Filename = Path.Combine( UserConfigurationFolder, 
				UserConfigurationFilename );
			
			Save( Filename );
		}
		
		/// <summary>
		/// Saves the configuration using the specified writer.
		/// </summary>
		/// <param name="writer">A text writer.</param>
		public void Save( TextWriter writer )
		{
			XmlSerializer Serializer = 
				new XmlSerializer( typeof( SoapTraceConfiguration ) );
			
			Serializer.Serialize( writer, this );
			
			writer.Close( );		
		}
		
		/// <summary>
		/// Saves the configuration to a file.
		/// </summary>
		/// <param name="filename">The name of the 
		/// saved configuration file.</param>
		public void Save( string filename )
		{
			StreamWriter Writer = 
				new StreamWriter( filename, false, Encoding.UTF8 );
						
			Save( Writer );
		}
		
		/// <summary>
		/// Gets the formatter entries that are specified in the config file.
		/// </summary>
		[ XmlArray( "messageFormatters" ) ]
		public MessageFormatterEntryCollection MessageFormatterEntries
		{
			get
			{
				return m_FormatterEntries;
			}
		}
		
		/// <summary>
		/// Gets the monitor manager entries that are specified in 
		/// the config file.
		/// </summary>
		[ XmlArray( "soapMessageMonitors" ) ]
		public MonitorManagerConfigurationCollection MonitorManagerConfigurationCollection
		{
			get
			{
				return m_MonitorManagers;
			}
		}		
		
		/// <summary>
		/// Gets the monitor manager entries that have been closed.
		/// </summary>
		[ XmlArray( "closedSoapMessageMonitors" ) ]
		public MonitorManagerConfigurationCollection ClosedMonitorManagerConfigurationCollection
		{
			get
			{
				return m_ClosedMonitorManagers;
			}
		}
		
		/// <summary>
		/// Gets or sets the number of closed manager entries to keep. 
		/// </summary>
		[ XmlElement( "maxCloseHistory" ) ]
		public int MaxCloseHistoryItems
		{
			get
			{
				return m_MaxCloseHistoryItems;
			}
			
			set
			{
				m_MaxCloseHistoryItems = value;
			}
		}	
		
		/// <summary>
		/// This flag specifies whether the "Debug Messages" menu option. 
		/// </summary>
		[ XmlElement( "debugMessages" ) ]
		public bool DebugMessages
		{
			get
			{
				return m_DebugMessages;
			}
			
			set
			{
				m_DebugMessages = value;
			}
		}
		
		/// <summary>
		/// Gets or sets the number of debug messages to save. 
		/// </summary>
		[ XmlElement( "debugMessagesCount" ) ]
		public int DebugMessagesCount
		{
			get
			{
				return m_DebugMessagesCount;
			}
			
			set
			{
				m_DebugMessagesCount = value;
			}
		}		
		
		/// <summary>
		/// Gets or sets the debug log level to be used whilst running.
		/// </summary>
		[ XmlElement( "debugLogLevel" ) ]
		public LogLevel DebugLogLevel
		{
			get
			{
				return m_DebugLogLevel;
			}
			
			set
			{
				m_DebugLogLevel = value;
			}
		}
		
		/// <summary>
		/// Gets or sets whether bytes should be converted to a UTF8 string
		/// or written as bytes when debug logging. If the SoapTrace app
		/// is being used with HTTP requests then logging as a string makes
		/// the debug information easier to read. However if the data is not
		/// HTTP then logging as bytes is more useful.
		/// </summary>
		[ XmlElement( "debugLogBytesAsString" ) ]
		public bool DebugLogBytesAsString
		{
			get
			{
				return m_DebugLogBytesAsString;
			}
			
			set
			{
				m_DebugLogBytesAsString = value;
			}
		}
		
		/// <summary>
		/// Gets or sets the main form's configuration.
		/// </summary>
		[ XmlElement( "mainForm" ) ]
		public MainFormConfiguration MainFormConfiguration
		{
			get
			{
				return m_MainFormConfig;
			}
			
			set
			{
				m_MainFormConfig = value;
			}
		}
	
		/// <summary>
		/// Gets or sets the soap message logger's config. 
		/// </summary>
		[ XmlElement( "soapMessageLogger" ) ]
		public SoapMessageLoggerConfiguration SoapMessageLoggerConfiguration
		{
			get
			{
				return m_SoapMessageLoggerConfig;
			}
			
			set
			{
				m_SoapMessageLoggerConfig = value;
			}
		}
		
		/// <summary>
		/// Gets whether there are any saved user settings.
		/// </summary>
		private static bool UserSettingsExist
		{
			get
			{
				return File.Exists( UserConfigurationFullFilename );
			}
		}
		
		/// <summary>
		/// Gets the user configuration filename including the path.
		/// </summary>
		private static string UserConfigurationFullFilename
		{
			get
			{
				return Path.Combine( UserConfigurationFolder, UserConfigurationFilename );
			}
		}
	}
}
